﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace AsyncDelegateForm
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private delegate void InvokeDelegate();
         private delegate void SetTextBoxHandler(TextBox tb,string str);

         private InvokeDelegate invokeDelegate;
         private SetTextBoxHandler deleChangeText;

        private void FormTest_Load(object sender, EventArgs e)
         {
             //初始化两个代理实例
             this.invokeDelegate = new InvokeDelegate(this.FunTest);
             this.deleChangeText = new SetTextBoxHandler(this.SetTextBoxValue);
         }

         private void FunTest()
         {
             for (int i = 0; i < 100000; i++)
             {
                 //搜索控件句柄，判断控件是否生成，不生成则返回false，此时就不能调用begininvoke方法了
                 //另外，如果对if内部语句的调用发生在同一线程（即UI线程或主线程），则InvokeRequired将返回false；
                 if (this.textBox1.InvokeRequired)
                 {
                     this.BeginInvoke(this.deleChangeText, new object[] { this.textBox1, i.ToString() });
                     //一定注意，Sleep的动作一定不能放在SetTextBoxValue（）方法中，因为控件的BeginInvoke（）会将SetTextBoxValue（）方法
                     //封送至后台线程，这就变成了在后台线程中让主线程Sleep300ms的时间，而不是让后台线程Sleep300ms了。
                     Thread.Sleep(300);
                 }
                 else
                 {
                     this.SetTextBoxValue(this.textBox1, i.ToString());
                     Thread.Sleep(300);
                 }
             }
             
         }

         private void SetTextBoxValue(TextBox tb, string str)
         {
             tb.Text = str;
             tb.Refresh();
             //下面的句子表明，即使该方法被封送到后台线程后，该方法内的线程是主线程，而非后台线程
             //MessageBox.Show(Thread.CurrentThread.IsBackground.ToString());
         }

         //在后台线程中调用FunTest()
         private void button1_Click(object sender, EventArgs e)
         {
             //使用异步调用，开辟后台线程
             this.invokeDelegate.BeginInvoke(null, null);
         }

         //在UI线程中调用FunTest()
         private void button2_Click(object sender, EventArgs e)
         {
             this.FunTest();
         }

         //使用代理调用函数，结果同button2_Click（）
         private void button3_Click(object sender, EventArgs e)
         {
             this.invokeDelegate();
         }
    }
}
